package sample.note;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.*;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.CalendarContract;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.preference.PreferenceManager;
import lombok.SneakyThrows;
import okhttp3.OkHttpClient;

import javax.net.ssl.*;
import java.io.IOException;
import java.lang.reflect.Field;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.*;

import static android.provider.CalendarContract.Events.DESCRIPTION;
import static android.provider.CalendarContract.Events.EVENT_LOCATION;
import static android.provider.CalendarContract.Events.TITLE;

public class AppWrapper extends Application {
   public static Context appContext;
   CrashHandler crashHandler;

   public static Context getContext(){
      return appContext;
   }
   @Override
   public void onCreate() {
      super.onCreate();
      appContext = getApplicationContext();

      /* If you has other classes that need context object to initialize when application is created,
         you can use the appContext here to process. */
      crashHandler = CrashHandler.getInstance();
      crashHandler.boot(this);
   }

   public void onTerminate() {
      super.onTerminate();
      crashHandler.shutdown();
   }
   public static void cheers(String msg){
      Toast.makeText(appContext, msg, Toast.LENGTH_LONG).show();
   }

   @SneakyThrows
   public static String host() throws IOException {

      SharedPreferences opt=
         PreferenceManager.getDefaultSharedPreferences(appContext);
      String host = opt.getString("prefix", Property.get("host"));
      Log.i("get host", host);
      return host;
   }

   @SneakyThrows
   public static String prop(String key) throws IOException {

      SharedPreferences opt=
         PreferenceManager.getDefaultSharedPreferences(appContext);
      String val= opt.getString(key, Property.get(key));
      Log.i(key, val);
      return val;
   }
   public static void error(Context ctx, String hint, Exception e) {
      Log.e("Notes: ", hint, e);
      Toast.makeText(ctx, hint + e.getMessage(), Toast.LENGTH_LONG).show();
   }

   public static OkHttpClient okHttpClient() throws NoSuchAlgorithmException, KeyManagementException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
      OkHttpClient hc = new OkHttpClient();
      SSLContext sc = null;
      sc = SSLContext.getInstance("SSL");
      sc.init(null, new TrustManager[]{new X509TrustManager() {
         public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
         }

         public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
         }

         public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
         }
      }}, new SecureRandom());

      HostnameVerifier hv = new HostnameVerifier() {
         @Override
         public boolean verify(String hostname, SSLSession session) {
            return true;
         }
      };

      Class clazz = Class.forName("okhttp3.OkHttpClient");
      Field hostnameVerifier = clazz.getDeclaredField("hostnameVerifier");
      hostnameVerifier.setAccessible(true);
      hostnameVerifier.set(hc, hv);

      Field sslSocketFactory = clazz.getDeclaredField("sslSocketFactoryOrNull");
      sslSocketFactory.setAccessible(true);
      sslSocketFactory.set(hc, sc.getSocketFactory());

      return hc;
   }
   public static boolean reqPermit(String[] Manifest_permission_strList, Activity context) {
      List<String> notAllowed = new ArrayList<String>();
      for(int i=0; i<Manifest_permission_strList.length; i++){
         String Manifest_permission_str = Manifest_permission_strList[i];
         int checkSelfPermission= ActivityCompat.checkSelfPermission(context, Manifest_permission_str);

         if (checkSelfPermission == PackageManager.PERMISSION_GRANTED) {
            continue;
         }
         notAllowed.add(Manifest_permission_str);
      }
      if(notAllowed.size() == 0){
         return true;
      }
      String[] notAllowedList = notAllowed.toArray(new String[notAllowed.size()]);
      ActivityCompat.requestPermissions(context, notAllowedList, 0);
      return false;
   }

   // permission
   public static boolean reqPermit(String Manifest_permission_str, Activity context) {
      int checkSelfPermission= ActivityCompat.checkSelfPermission(context, Manifest_permission_str);

      if (checkSelfPermission == PackageManager.PERMISSION_GRANTED) {
         return true;
      }
      ActivityCompat.requestPermissions(context,new String[]{Manifest_permission_str}, 0);
      return false;
   }
   public boolean onRequestPermissionsResult(Activity context, String[] permissions, int[] grantResults) {
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
         return true;
      }
      if (!ActivityCompat.shouldShowRequestPermissionRationale(context, permissions[0])) {
         gotoSettings();
      }
      return false;
   }
   public static void gotoSettings(){
      Intent localIntent = new Intent();
      localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      if (Build.VERSION.SDK_INT >= 9) {
         localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
         localIntent.setData(Uri.fromParts("package", appContext.getPackageName(), null));
      }
      localIntent.setAction(Intent.ACTION_VIEW);
      localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
      localIntent.putExtra("com.android.settings.ApplicationPkgName", appContext.getPackageName());
      appContext.startActivity(localIntent);
   }
   public static int getProcessId(){
      ActivityManager am = (ActivityManager)appContext.getSystemService(Context.ACTIVITY_SERVICE);
      List<ActivityManager.RunningAppProcessInfo> pids = am.getRunningAppProcesses();
      int processid = 0;
      for(int i = 0; i < pids.size(); i++)
      {
         ActivityManager.RunningAppProcessInfo info = pids.get(i);
         if(info.processName.equalsIgnoreCase("here your package name")){
            processid = info.pid;
         }
      }
      return processid;
   }
   public static void getPkgInfo(){
      PackageManager pm = appContext.getPackageManager();
      Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
      mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
      List<ResolveInfo> resolveInfoList = pm
         .queryIntentActivities(mainIntent, PackageManager.MATCH_DEFAULT_ONLY);
      Collections.sort(resolveInfoList,new ResolveInfo.DisplayNameComparator(pm));
      for (ResolveInfo reInfo : resolveInfoList) {
         //String pkgName = reInfo.activityInfo.packageName;
      }
   }
   public static void insertEvent(){
      Intent calIntent = new Intent(Intent.ACTION_INSERT);
      calIntent.setType("vnd.android.cursor.item/event");
      calIntent.putExtra(TITLE, "My House Party");
      calIntent.putExtra(EVENT_LOCATION, "My Beach House");
      calIntent.putExtra(DESCRIPTION, "A Pig Roast on the Beach");
      GregorianCalendar calDate = new GregorianCalendar(2012, 7, 15);
      calIntent.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, true);
      calIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME,
            calDate.getTimeInMillis());
      calIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME,
            calDate.getTimeInMillis());
      calIntent.putExtra(CalendarContract.Events.ACCESS_LEVEL, CalendarContract.Events.ACCESS_PRIVATE);
      calIntent.putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY);
      calIntent.putExtra(CalendarContract.Events.RRULE, "FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH");
      appContext.startActivity(calIntent);
   }
   public static void insertEventContent(){
      //Uri CALENDAR_URI = Uri.parse("content://calendar/events");
      ContentResolver cr = appContext.getContentResolver();
      ContentValues values = new ContentValues();

      GregorianCalendar calDate = new GregorianCalendar(2012, 7, 15);
      values.put("eventTimezone", TimeZone.getDefault().getID());
      values.put("calendar_id", 1);
      values.put("title", "ttt");
      //values.put("allDay", 0);
      values.put("dtstart", calDate.getTimeInMillis());
      values.put("dtend", calDate.getTimeInMillis());
      values.put("description", "xxx");
      values.put("eventLocation", "");
      //values.put("visibility", CalendarContract.Events.AVAILABILITY_BUSY);
      values.put("hasAlarm", true);
      cr.insert(CalendarContract.Events.CONTENT_URI, values);

      /*
         int id = 1; 
      // calendar entry ID
      Uri uri = ContentUris.withAppendedId(CALENDAR_URI, id);
      cr.delete(uri, null, null);
      */
   }
   public static List<Map<String,String>> queryEventContent(){
      String[] columns = new String[]{"title", "description", "eventLocation", "dtstart"};
      List<Map<String,String>> rows = new ArrayList<>();

      queryEventContent(cur -> {
         Map<String,String> row = new HashMap<>();
         for(String i: columns){
            String val= cur.getString(cur.getColumnIndex(i));
            row.put(i, val);
         }
         rows.add(row);
      });
      return rows;
   }

   @FunctionalInterface
   public interface LoopCursor {
      void process(Cursor c);
   }
   public static void queryEventContent(LoopCursor loopCur){
      //Uri uri = Uri.parse("content://com.android.calendar/events");
      Cursor eventCursor = appContext.getContentResolver().query(CalendarContract.Events.CONTENT_URI, null, null, null, null);
      //CalendarContract.EventsColumns.CALENDAR_ID;

      while (eventCursor.moveToNext()) {
         loopCur.process(eventCursor);
      }
   }
}
